<template>
  <a-modal
    class="imageCropper"
    v-model:visible="visible"
    title="编辑图片"
    :footer="false"
    @cancel="closeModel"
  >
    <!-- 图片裁剪 -->
    <vue-cropper
      ref="cropperRef"
      :img="imageUrl"
      output-type="png"
      :info="true"
      :can-move-box="true"
      :fixed-box="false"
      :auto-crop="true"
      :center-box="true"
      :canMove="false"
    ></vue-cropper>

    <div style="margin-bottom: 16px"></div>
    <!-- 图片协同编辑操作 -->
    <div class="image-edit-actions" v-if="isTeamSpace">
      <a-space>
        <a-button v-if="editingUser" disable @click="changeScale(1)"
          >{{ editingUser?.userName }}正在编辑</a-button
        >
        <a-button v-if="canEnterEdit" type="primary" ghost @click="enterEdit">进入编辑</a-button>
        <a-button v-if="canExitEdit" type="danger" ghost @click="exitExit">退出编辑</a-button>
      </a-space>
    </div>

    <div style="margin-bottom: 16px"></div>
    <!-- 图片操作 -->
    <div class="image-cropper-action">
      <a-space>
        <a-button @click="rotateLeft" :disabled="!canEdit">向左旋转</a-button>
        <a-button @click="rotateRight" :disabled="!canEdit">向右旋转</a-button>
        <a-button @click="changeScale(1)" :disabled="!canEdit">放大</a-button>
        <a-button @click="changeScale(-1)" :disabled="!canEdit">缩小</a-button>
        <a-button type="primary" :loading="loading" @click="handleConfirm" :disabled="!canEdit"
          >确认</a-button
        >
      </a-space>
    </div>
  </a-modal>
</template>

<script setup lang="ts">
import { computed, onUnmounted, ref, watchEffect } from 'vue'
import { message } from 'ant-design-vue'
import { uploadPictureUsingPost } from '@/api/pictureController'
import { userLoginStore } from '@/stores/userLoginStore'
import PictureEditWebSocket from '@/utils/pictureEditWebSocket'
import { PICTURE_EDIT_ACTION_ENUM, PICTURE_EDIT_MESSAGE_TYPE_ENUM } from '@/constants/picture'
import { SPACE_TYPE_ENUM } from '@/constants/space'
const visible = ref(false)
interface Props {
  imageUrl: string
  picture?: API.PictureVO
  spaceId?: number
  space?: API.SpaceVO
  onSuccess?: (newPicture: API.PictureVO) => void
}
const props = defineProps<Props>()

//获取图片裁切框的引用
const cropperRef = ref(null)
// 是否为团队空间
const isTeamSpace = computed(() => {
  console.log(props.space?.spaceType)

  return props.space?.spaceType === SPACE_TYPE_ENUM.TEAM
})

//确认裁切
const handleConfirm = () => {
  cropperRef.value.getCropBlob((blob: Blob) => {
    //blob为已经裁切好的文件
    const fileName = (props.picture?.name || 'image') + '.png'
    const file = new File([blob], fileName, { type: 'image/png' })
    //调用上传图片接口
    handleUpload({ file })
  })
}
const loading = ref(false)

//进入编辑
const enterEdit = () => {
  if (webSocket) {
    //发送进入编辑的消息
    webSocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT,
    })
  }
}

//退出编辑
const exitExit = () => {
  if (webSocket) {
    //发送进入编辑的消息
    webSocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT,
    })
  }
}
//编辑图片操作
const editAction = (action: string) => {
  if (webSocket) {
    //发送进入编辑的消息
    webSocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION,
      editAction: action,
    })
  }
}
/**
 * 上传图片
 * @param file
 */
const handleUpload = async ({ file }: any) => {
  loading.value = true
  try {
    const params: API.PictureUploadDTO = props.picture ? { id: props.picture.id } : {}
    params.spaceId = props.spaceId
    const res = await uploadPictureUsingPost(params, {}, file)
    if (res.data.code === 200) {
      message.success('上传成功')
      props.onSuccess?.(res.data.data)
      closeModel()
    } else {
      message.error('上传失败：' + res.data.data)
    }
  } catch (error) {
    message.error('上传异常')
  }
  loading.value = false
}
/* 缩放比例 */
const changeScale = (num) => {
  cropperRef.value.changeScale(num)
  if (num > 0) {
    editAction(PICTURE_EDIT_ACTION_ENUM.ZOOM_IN)
  } else {
    editAction(PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT)
  }
}

// 打开弹窗
function openModel() {
  visible.value = true
}
// 关闭弹窗
const closeModel = () => {
  visible.value = false
  //断开连接
  if (webSocket) {
    webSocket.disconnect()
  }
  editingUser.value = null
}
defineExpose({ openModel })
/* 实时编辑 */
const loginUserStore = userLoginStore()
const loginUser = loginUserStore.loginUser
//正在编辑的用户
const editingUser = ref<API.UserVO>()
//当前用户是否可进入编辑
const canEnterEdit = computed(() => {
  return !editingUser.value
})
//当前用户是本人就能进入编辑
const canExitEdit = computed(() => {
  return editingUser.value?.id === loginUser.id
})
//当前用户是本人就能进入编辑
const canEdit = computed(() => {
  if (!isTeamSpace.value) {
    return true
  }
  return editingUser.value?.id === loginUser.id
})

//编写webSocket逻辑
let webSocket: PictureEditWebSocket | null
//初始化webSocket连接，绑定监听事件
const initWebSocket = () => {
  const pictureId = props.picture?.id
  if (!pictureId || !visible.value) {
    return
  }
  //防止之前的连接的未释放
  if (webSocket) {
    webSocket.disconnect()
  }
  webSocket = new PictureEditWebSocket(pictureId)
  //建立连接
  webSocket.connect()
  webSocket.on('open', (msg) => {
    console.log('连接成功')
    if (msg.user) {
      editingUser.value = msg.user
    }
  })
  //监听一系列的事件
  webSocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.INFO, (msg) => {
    console.log('收到信息', msg)
    message.info(msg.message)
  })
  webSocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ERROR, (msg) => {
    console.log('收到错误通知', msg)
    message.info(msg.message)
  })
  webSocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT, (msg) => {
    console.log('收到进入编辑通知', msg)
    message.info(msg.message)
    editingUser.value = msg.user
  })
  webSocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT, (msg) => {
    console.log('收到退出编辑通知', msg)
    editingUser.value = null
  })
  //监听图片编辑行为
  webSocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION, (msg) => {
    console.log('收到退出编辑通知', msg)
    message.info(msg.message)
    switch (msg.editAction) {
      case PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT:
        rotateLeft()
        break
      case PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT:
        rotateRight()
        break
      case PICTURE_EDIT_ACTION_ENUM.ZOOM_IN:
        changeScale(1)
        break
      case PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT:
        changeScale(-1)
        break
    }
  })
}

//旋转
const rotateLeft = () => {
  cropperRef.value.rotateLeft()
  editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT)
}
const rotateRight = () => {
  cropperRef.value.rotateRight()
  editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT)
}
//监听图片编辑行为
watchEffect(() => {
  if (isTeamSpace.value) {
    initWebSocket()
  }
})
//组件销毁时断开连接
onUnmounted(() => {
  //断开连接
  if (webSocket) {
    webSocket.disconnect()
  }
  editingUser.value = null
})
</script>

<style>
.imageCropper {
  text-align: center;
}
.imageCropper .vue-cropper {
  width: 100%;
  height: 400px;
}
</style>